<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>定时任务列表渲染</title>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
      font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    }

    body {
      background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%);
      color: #333;
      line-height: 1.6;
      min-height: 100vh;
      padding: 20px;
    }

    .container {
      max-width: 1200px;
      margin: 0 auto;
    }

    header {
      text-align: center;
      padding: 40px 20px;
      color: white;
    }

    h1 {
      font-size: 2.8rem;
      margin-bottom: 15px;
      text-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
    }

    .subtitle {
      font-size: 1.2rem;
      max-width: 700px;
      margin: 0 auto 30px;
      opacity: 0.9;
    }

    .card {
      background: white;
      border-radius: 15px;
      box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15);
      overflow: hidden;
      margin-bottom: 30px;
    }

    .controls {
      padding: 25px;
      display: flex;
      flex-wrap: wrap;
      gap: 15px;
      align-items: center;
      background: #f8f9fa;
      border-bottom: 1px solid #eee;
    }

    .search-box {
      flex: 1;
      min-width: 250px;
      position: relative;
    }

    .search-box input {
      width: 100%;
      padding: 14px 20px 14px 50px;
      border: 2px solid #e0e0e0;
      border-radius: 50px;
      font-size: 16px;
      transition: all 0.3s;
    }

    .search-box input:focus {
      outline: none;
      border-color: #2575fc;
      box-shadow: 0 0 0 3px rgba(37, 117, 252, 0.2);
    }

    .search-box i {
      position: absolute;
      left: 20px;
      top: 50%;
      transform: translateY(-50%);
      color: #777;
    }

    .filter-group {
      display: flex;
      gap: 15px;
      flex-wrap: wrap;
    }

    select {
      padding: 12px 20px;
      border: 2px solid #e0e0e0;
      border-radius: 50px;
      background: white;
      font-size: 16px;
      cursor: pointer;
    }

    button {
      background: linear-gradient(to right, #6a11cb, #2575fc);
      color: white;
      border: none;
      padding: 14px 30px;
      border-radius: 50px;
      font-size: 16px;
      font-weight: 600;
      cursor: pointer;
      transition: all 0.3s;
      box-shadow: 0 4px 15px rgba(106, 17, 203, 0.3);
    }

    button:hover {
      transform: translateY(-2px);
      box-shadow: 0 6px 20px rgba(106, 17, 203, 0.4);
    }

    .content {
      padding: 30px;
    }

    .loading {
      text-align: center;
      padding: 50px;
      display: none;
    }

    .spinner {
      width: 50px;
      height: 50px;
      border: 5px solid rgba(37, 117, 252, 0.2);
      border-top: 5px solid #2575fc;
      border-radius: 50%;
      margin: 0 auto 20px;
      animation: spin 1s linear infinite;
    }

    @keyframes spin {
      0% { transform: rotate(0deg); }
      100% { transform: rotate(360deg); }
    }

    .error {
      background: #ffebee;
      color: #c62828;
      padding: 20px;
      border-radius: 10px;
      text-align: center;
      margin: 20px 0;
      display: none;
    }

    .data-container {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
      gap: 25px;
      margin-top: 20px;
    }

    .data-card {
      background: white;
      border-radius: 12px;
      overflow: hidden;
      box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08);
      transition: transform 0.3s, box-shadow 0.3s;
      border: 1px solid #eee;
    }

    .data-card:hover {
      transform: translateY(-5px);
      box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
    }

    .card-header {
      background: linear-gradient(to right, #6a11cb, #2575fc);
      color: white;
      padding: 20px;
    }

    .card-body {
      padding: 20px;
    }

    .card-body p {
      margin-bottom: 12px;
      color: #555;
    }

    .card-body strong {
      color: #333;
      font-weight: 600;
    }

    .user-id {
      display: inline-block;
      background: rgba(255, 255, 255, 0.2);
      padding: 3px 10px;
      border-radius: 20px;
      font-size: 0.9rem;
      margin-bottom: 10px;
    }

    footer {
      text-align: center;
      padding: 30px;
      color: rgba(255, 255, 255, 0.7);
      font-size: 0.9rem;
    }

    @media (max-width: 768px) {
      .controls {
        flex-direction: column;
        align-items: stretch;
      }

      .filter-group {
        flex-direction: column;
      }

      h1 {
        font-size: 2.2rem;
      }
    }
  </style>
</head>
<body>
<div class="container">
  <header>
    <h1>自定义定时任务数据查询与列表渲染</h1>
    <p class="subtitle">自定义定时任务</p>
  </header>

  <main>
    <div class="card">
      <div class="controls">
        <div class="search-box">
          <i class="fas fa-search"></i>
          <input type="text" id="searchInput" placeholder="搜索任务...">
        </div>

        <div class="filter-group">
          <select id="filterSelect">
            <option value="all">全部任务</option>
            <option value="completed">已完成</option>
            <option value="pending">进行中</option>
          </select>

          <select id="sortSelect">
            <option value="asc">ID 升序</option>
            <option value="desc">ID 降序</option>
          </select>
        </div>

        <button id="fetchData">
          <i class="fas fa-sync-alt"></i> 获取数据
        </button>
      </div>

      <div class="content">
        <div class="loading" id="loadingIndicator">
          <div class="spinner"></div>
          <p>正在加载数据，请稍候...</p>
        </div>

        <div class="error" id="errorMessage">
          <i class="fas fa-exclamation-triangle"></i>
          <p id="errorText">加载数据时出错，请稍后再试</p>
        </div>

        <div class="data-container" id="dataContainer">
          <!-- 数据卡片将通过JavaScript动态生成 -->
        </div>
      </div>
    </div>
  </main>

  <footer>
    <p>© 2023 API数据查询页面 | 模拟数据来自JSONPlaceholder API</p>
  </footer>
</div>

<script>
  // 模拟API数据（实际应用中会从真实API获取）
  const mockApiData = [
    {
      id: 1,
      name: "张三",
      email: "zhangsan@example.com",
      status: "completed",
      task: "开发登录页面",
      description: "完成了任务登录界面的设计和功能实现"
    },
    {
      id: 2,
      name: "李四",
      email: "lisi@example.com",
      status: "pending",
      task: "数据库优化",
      description: "正在进行数据库查询性能的优化工作"
    },
    {
      id: 3,
      name: "王五",
      email: "wangwu@example.com",
      status: "completed",
      task: "API接口开发",
      description: "已完成任务管理模块的API接口开发"
    },
    {
      id: 4,
      name: "赵六",
      email: "zhaoliu@example.com",
      status: "pending",
      task: "移动端适配",
      description: "正在进行响应式设计的移动端适配工作"
    },
    {
      id: 5,
      name: "钱七",
      email: "qianqi@example.com",
      status: "completed",
      task: "测试用例编写",
      description: "已完成核心功能的测试用例编写和评审"
    },
    {
      id: 6,
      name: "孙八",
      email: "sunba@example.com",
      status: "pending",
      task: "项目文档整理",
      description: "正在进行项目文档的整理和归档工作"
    },
    {
      id: 7,
      name: "周九",
      email: "zhoujiu@example.com",
      status: "completed",
      task: "部署上线",
      description: "已完成项目v1.0版本的部署上线工作"
    },
    {
      id: 8,
      name: "吴十",
      email: "wushi@example.com",
      status: "pending",
      task: "性能测试",
      description: "正在进行系统压力测试和性能优化"
    }
  ];

  // DOM元素
  const fetchDataBtn = document.getElementById('fetchData');
  const dataContainer = document.getElementById('dataContainer');
  const loadingIndicator = document.getElementById('loadingIndicator');
  const errorMessage = document.getElementById('errorMessage');
  const searchInput = document.getElementById('searchInput');
  const filterSelect = document.getElementById('filterSelect');
  const sortSelect = document.getElementById('sortSelect');

  // 显示加载状态
  function showLoading() {
    loadingIndicator.style.display = 'block';
    errorMessage.style.display = 'none';
    dataContainer.innerHTML = '';
  }

  // 隐藏加载状态
  function hideLoading() {
    loadingIndicator.style.display = 'none';
  }

  // 显示错误信息
  function showError(message) {
    errorMessage.style.display = 'block';
    document.getElementById('errorText').textContent = message;
  }

  // 渲染数据卡片
  function renderData(data) {
    dataContainer.innerHTML = '';

    if (data.length === 0) {
      dataContainer.innerHTML = `<div class="no-results">没有找到匹配的数据</div>`;
      return;
    }

    data.forEach(item => {
      const statusClass = item.triggerStatus === 0 ? 'completed' : 'pending';
      const statusText = item.triggerStatus === 0 ? '已禁止' : '进行中';

      const card = document.createElement('div');
      card.className = 'data-card';
      card.innerHTML = `
                    <div class="card-header">
                        <span class="user-id">ID: ${item.id}</span>
                        <h3>${item.jobDesc}</h3>
                    </div>
                    <div class="card-body">
                        <p><strong>任务描述:</strong> ${item.jobDesc}</p>
                        <p><strong>cron表达式:</strong> ${item.scheduleConf}</p>
                        <p><strong>处理器:</strong> ${item.executorHandler}</p>
                        <p><strong>状态:</strong> <span class="status ${statusClass}">${statusText}</span></p>
                        <button class="trigger-btn" onclick="triggerJob(${item.id})">
                            <i class="fas fa-play"></i> 触发任务
                        </button>
                    </div>
                `;
      dataContainer.appendChild(card);
    });
  }

  // API请求
  async function getJobListApi() {
    const response = await fetch('http://localhost:5001/jobinfo/jobList', {
              method: 'POST', // 指定请求方法为POST
              headers: {'Content-Type': 'application/json'}
    })
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    return await response.json();
  }
  // API请求
  async function triggerJobApi(id) {
    const response = await fetch('http://localhost:5001/jobinfo/triggerJob?jobId=' + id, {
              method: 'GET', // 指定请求方法为POST
              headers: {'Content-Type': 'application/json'}
    })
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
  }

  // 获取并处理数据
  async function getData() {
    showLoading();
    try {
      const data = await getJobListApi();
      hideLoading();
      processAndRenderData(data);
    } catch (error) {
      hideLoading();
      showError(error);
    }
  }
  // 获取并处理数据
  async function triggerJob(id) {
    showLoading();
    try {
      await triggerJobApi(id);
      getData()
      hideLoading();
    } catch (error) {
      hideLoading();
      showError(error);
    }
  }

  // 处理并渲染数据（包含搜索和过滤）
  function processAndRenderData(data) {
    // 渲染数据
    renderData(data);
  }

  // 事件监听
  fetchDataBtn.addEventListener('click', getData);
  searchInput.addEventListener('input', () => getData);
  filterSelect.addEventListener('change', () => getData);
  sortSelect.addEventListener('change', () => getData);

  // 初始加载数据
  document.addEventListener('DOMContentLoaded', () => {
    // renderData(mockApiData);
    getData()
  });
</script>
</body>
</html>